/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#ifndef BYTEBUFFER_HPP
#define BYTEBUFFER_HPP

#include "cpputils/CppUtils.hpp"

namespace cpputils {
	/**
	 * Basic input/output streaming facilities
	 */
	namespace io {
		/**
		 * The represantion for byte buffer with the specified capacity and len.
		 * The capacity/len can be changed at runtime without lost data.
		 * @par Usage:
		 * @code
		 * // Creation a byte buffer with initial capacity 1024 bytes
		 * ByteBuffer* myBuffer = new ByteBuffer( 1024 );
		 *
		 * // Appending a C-style buffer
		 * const unsigned char cStyleBuffer[] =  { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
		 * myBuffer->append (cStyleBuffer, sizeof ( cStyleBuffer ) );
		 *
		 * // Appending another ByteBuffer
		 * ByteBuffer* anotherBuffer = ...
		 * ...
		 * myBuffer->append ( anotherBuffer );
		 *
		 * // Len of buffer
		 * myBuffer->getLen();
		 * // Capacity of buffer
		 * myBuffer->getCapacity();
		 * // Resizing without lost current data
		 * myBuffer->setLen ( 2048 );
		 *
		 * // Filling a buffer with zero
		 * myBuffer->fill ( 0 );
		 *
		 * // Setting up buffer to other point
		 * unsigned char* otherPoint = new unsigned char[255];
		 * ...
		 * myBuffer->setup ( otherPoint , 255 );
		 * @endcode
		 */
		class ByteBuffer : public RefObject {
		private:
			unsigned int m_nLen;
			unsigned int m_nCapacity;
			unsigned int m_nMaxCapacity;
			unsigned char* m_aData;
			bool m_bAutoDisposeFlag;

			unsigned int m_nPos;
			unsigned int m_nMarkedLen;
			unsigned int m_nMarkedPos;

			inline void disposeCurrent();
			inline void grow(unsigned int nNewLen);
		public:
			typedef boost::shared_ptr < ByteBuffer > SharedPtr;

			inline unsigned char* getData() const;
			inline unsigned char* getDataAtPos() const;
			inline unsigned char* getDataAtPos(int nPos) const;
			inline unsigned int getLen() const;
			inline unsigned int getLenFromPos() const;
			inline void setLen(unsigned int nNewLen);
			inline unsigned int getCapacity() const;
			inline void setCapacity(unsigned int nCapacity);
			inline unsigned int getMaxCapacity() const;
			inline void setMaxCapacity(unsigned int nCapacity);
			inline unsigned int getAvailableCapacity() const;
			inline unsigned int getPos() const;
			inline void setPos(unsigned int nNewPos);
			inline void seek ( int nStep );

			inline void mark();
			inline void resetToMarker();

			inline void clear();

			inline void setup(
				unsigned char* aBuffer,
				unsigned int nLen,
				bool bCopingMode=false,
				bool bAutoDispose=false
			);

			inline void append ( const unsigned char* aBuffer, const unsigned int nBufLen );
			inline void append ( const unsigned char nByte );
			inline void append ( const ByteBuffer& oBuffer );
			inline void append ( const ByteBuffer* poBuffer );

			inline void replace ( const unsigned char* aBuffer, const unsigned int nBufLen );
			inline void replace ( const ByteBuffer& oBuffer );
			inline void replace ( const ByteBuffer* poBuffer );

			inline void cut ( unsigned int nBeginPos, unsigned int nEndPos, ByteBuffer* oBuffer );
			inline void cut ( unsigned int nBeginPos, unsigned int nEndPos, ByteBuffer& oBuffer );
			inline void cut ( unsigned int nBeginPos, unsigned int nEndPos);
			inline void cut ( unsigned int nBeginPos, ByteBuffer* poBuffer );
			inline void cut ( unsigned int nBeginPos, ByteBuffer& oBuffer );
			inline void cut ( unsigned int nBeginPos );

			inline void fill ( int nValue );
			inline void fillToLen ( int nValue );
			inline void dump() const; // for debug purposes

			inline ByteBuffer();
			inline ByteBuffer(unsigned int nCapacity);
			inline ByteBuffer(unsigned int nCapacity, unsigned int nMaxCapacity);
			inline ByteBuffer(const ByteBuffer* poSrcBuffer);
			inline ByteBuffer(const ByteBuffer& oSrcBuffer);
			inline ByteBuffer(const unsigned char* poSrcBuffer, unsigned int nSrcBufLen, bool bCopingMode=true, bool bAutoDispose=true);
			inline ~ByteBuffer();
		};

		#include "ByteBuffer.inl"
	}
}

#endif // BYTEBUFFER_HPP
